{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using hypothesis to find interesting examples\n",
    "\n",
    "Hypothesis is a powerful and unique library for testing code. It also includes a `find` function for finding examples that satisfy an arbitrary predicate. Here, we will explore some of the neat things that can be found using this function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from hypothesis import find\n",
    "\n",
    "import dit\n",
    "from dit.abc import *\n",
    "from dit.pid import *\n",
    "from dit.utils.testing import distribution_structures\n",
    "\n",
    "dit.ditParams['repr.print'] = dit.ditParams['print.exact'] = True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To illustrate what the distribution source looks like, here we instantiate it with a `size` of 3 and an alphabet of `2`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = distribution_structures(size=3, alphabet=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Class:          Distribution\n",
       "Alphabet:       (0, 1) for all rvs\n",
       "Base:           linear\n",
       "Outcome Class:  tuple\n",
       "Outcome Length: 3\n",
       "RV Names:       None\n",
       "\n",
       "x           p(x)\n",
       "(0, 0, 0)   2667/18926\n",
       "(0, 0, 1)   4354/23287\n",
       "(0, 1, 0)   2735/34879\n",
       "(0, 1, 1)   5185/28822\n",
       "(1, 0, 0)   1049/14724\n",
       "(1, 0, 1)   5043/26701\n",
       "(1, 1, 0)   13331/95672\n",
       "(1, 1, 1)   775/54022"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.example()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Negativity of co-information"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pred(value):\n",
    "    return lambda d: dit.multivariate.coinformation(d) < value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class:          Distribution\n",
      "Alphabet:       (0, 1) for all rvs\n",
      "Base:           linear\n",
      "Outcome Class:  tuple\n",
      "Outcome Length: 3\n",
      "RV Names:       None\n",
      "\n",
      "x           p(x)\n",
      "(0, 0, 0)   1/3\n",
      "(0, 1, 1)   1/3\n",
      "(1, 0, 1)   1/3\n",
      "The coinformation is: -0.4150374992788435\n"
     ]
    }
   ],
   "source": [
    "ce = find(distribution_structures(3, 2), pred(-1e-5))\n",
    "print(ce)\n",
    "print(\"The coinformation is: {}\".format(dit.multivariate.coinformation(ce)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class:          Distribution\n",
      "Alphabet:       (0, 1) for all rvs\n",
      "Base:           linear\n",
      "Outcome Class:  tuple\n",
      "Outcome Length: 3\n",
      "RV Names:       None\n",
      "\n",
      "x           p(x)\n",
      "(0, 0, 0)   1/4\n",
      "(0, 1, 1)   1/4\n",
      "(1, 0, 1)   1/4\n",
      "(1, 1, 0)   1/4\n",
      "The coinformation is: -1.0\n"
     ]
    }
   ],
   "source": [
    "ce = find(distribution_structures(3, 2), pred(-0.5))\n",
    "print(ce)\n",
    "print(\"The coinformation is: {}\".format(dit.multivariate.coinformation(ce)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Gács-Körner common information is bound from above by the dual total correlation\n",
    "\n",
    "As we will see, hypothesis can not find an example of $K > B$, because one does not exist."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def b_lt_k(d):\n",
    "    k = dit.multivariate.gk_common_information(d)\n",
    "    b = dit.multivariate.dual_total_correlation(d)\n",
    "    return  k > b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "ename": "NoSuchExample",
     "evalue": "No examples found of condition b_lt_k",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNoSuchExample\u001b[0m                             Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-15-2c3dbd2b5e77>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdistribution_structures\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0malphabet\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0muniform\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb_lt_k\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/usr/local/lib/python3.6/site-packages/hypothesis/core.py\u001b[0m in \u001b[0;36mfind\u001b[0;34m(specifier, condition, settings, random, database_key)\u001b[0m\n\u001b[1;32m    800\u001b[0m                 runner.valid_examples,))\n\u001b[1;32m    801\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 802\u001b[0;31m     \u001b[0;32mraise\u001b[0m \u001b[0mNoSuchExample\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mget_pretty_function_description\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcondition\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNoSuchExample\u001b[0m: No examples found of condition b_lt_k"
     ]
    }
   ],
   "source": [
    "find(distribution_structures(size=3, alphabet=3, uniform=True), b_lt_k)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## BROJA is not Proj\n",
    "\n",
    "We know that the BROJA and Proj PID measures are not the same, but the BROJA paper did not provide any simple examples of this. Here, we find one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Class:          Distribution\n",
       "Alphabet:       (0, 1) for all rvs\n",
       "Base:           linear\n",
       "Outcome Class:  tuple\n",
       "Outcome Length: 3\n",
       "RV Names:       None\n",
       "\n",
       "x           p(x)\n",
       "(0, 1, 0)   1/4\n",
       "(1, 0, 1)   1/4\n",
       "(1, 1, 0)   1/4\n",
       "(1, 1, 1)   1/4"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ce = find(distribution_structures(3, 2, True), lambda d: PID_BROJA(d) != PID_Proj(d))\n",
    "ce"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+---------+--------+--------+\n",
      "| I_broja |  I_r   |   pi   |\n",
      "+---------+--------+--------+\n",
      "|  {0:1}  | 0.5000 | 0.0000 |\n",
      "|   {0}   | 0.3113 | 0.1887 |\n",
      "|   {1}   | 0.3113 | 0.1887 |\n",
      "|  {0}{1} | 0.1226 | 0.1226 |\n",
      "+---------+--------+--------+\n",
      "+--------+--------+--------+\n",
      "| I_proj |  I_r   |   pi   |\n",
      "+--------+--------+--------+\n",
      "| {0:1}  | 0.5000 | 0.0425 |\n",
      "|  {0}   | 0.3113 | 0.1462 |\n",
      "|  {1}   | 0.3113 | 0.1462 |\n",
      "| {0}{1} | 0.1650 | 0.1650 |\n",
      "+--------+--------+--------+\n"
     ]
    }
   ],
   "source": [
    "print(PID_BROJA(ce))\n",
    "print(PID_Proj(ce))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
